package com.google.untils.communicate;


import net.sf.json.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;

@Component
public class HttpClientBuilder {
    final static Logger logger = LoggerFactory.getLogger(HttpClientBuilder.class);

    private PoolingHttpClientConnectionManager connMgr;

    //最大连接数
    private final static int MaxTotalConnection = 800;

    //每个路由最大连接数
    private final static int MaxRouterConnction = 200;

    //获取连接的最大等待时间
    private final static int ConnectionPoolTimeout = 2000;

    //连接超时
    private final static int ConnectionTimeout = 60000;

    //请求超时
    private final static int SocketTimeout = 60000;

    private static  RequestConfig requestConfig;

    private static CloseableHttpClient httpClient;

    @PostConstruct
    public void init() {
        LayeredConnectionSocketFactory sslsf = null;
        try {
            sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
                .register("https", sslsf)
                .register("http", new PlainConnectionSocketFactory())
                .build();

        requestConfig=RequestConfig.custom().setConnectionRequestTimeout(ConnectionPoolTimeout).setConnectTimeout(ConnectionTimeout).setSocketTimeout(SocketTimeout).build();

        connMgr =new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        connMgr.setMaxTotal(MaxTotalConnection);
        connMgr.setDefaultMaxPerRoute(MaxRouterConnction);
    }

    //方案一，用连接池生成多个HttpClient,一个HttpClient执行一个HttpConnection
    public CloseableHttpClient getHttpClient() {
        httpClient = HttpClients.custom()
                .setConnectionManager(connMgr)
                .setDefaultRequestConfig(requestConfig)
                .build();
        return httpClient;
    }

    //方案二,全局只使用一个HttpClient
    public synchronized CloseableHttpClient  getSingleHttpClient() {
        if(httpClient==null){
            CloseableHttpClient httpClient = HttpClients.custom()
                    .setConnectionManager(connMgr)
                    .setDefaultRequestConfig(requestConfig)
                    .build();
            return httpClient;
        }else{
            return httpClient;
        }

    }

    public String getContent(HttpResponse response){
        JSONObject json = new JSONObject();
        if(response != null){
            ByteArrayOutputStream baos = null;
            InputStream is = null;
            HttpEntity entity=null;
            try {
                entity= response.getEntity();
                if(entity != null){
                    baos = new ByteArrayOutputStream();
                    is = entity.getContent();
                    byte[] buf = new byte[1024];
                    int len = -1;
                    while ((len = is.read(buf)) != -1) {
                        baos.write(buf, 0, len);
                    }
                }
                return new String(baos != null ? baos.toByteArray() : new byte[0],"UTF-8");
            }catch (Exception e) {
                logger.error("" + e);
                return e.getMessage();
            }finally {
                try {
                    if(baos != null) baos.close();
                    if(is != null) is.close();
                    EntityUtils.consume(entity);
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("" + e);
                }
            }
        }
        return null;
    }
}
